Finish templating MachObjectFile 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/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"
28
29 namespace llvm {
30 namespace object {
31
32 using support::endianness;
33
34 template<endianness E, bool B>
35 struct MachOType {
36   static const endianness TargetEndianness = E;
37   static const bool Is64Bits = B;
38 };
39
40 template<endianness TargetEndianness>
41 struct MachOInt24Impl;
42
43 template<>
44 struct MachOInt24Impl<support::little> {
45   uint8_t bytes[3];
46   operator uint32_t() const {
47     return (bytes[2] << 24) | (bytes[1] << 16) | bytes[0];
48   }
49 };
50
51 template<>
52 struct MachOInt24Impl<support::big> {
53   uint8_t bytes[3];
54   operator uint32_t() const {
55     return (bytes[0] << 24) | (bytes[1] << 16) | bytes[2];
56   }
57 };
58
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;
68 };
69
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;
75
76 template<class MachOT>
77 struct MachODataTypeTypedefHelper;
78
79 template<endianness TargetEndianness>
80 struct MachODataTypeTypedefHelper<MachOType<TargetEndianness, false> > {
81   typedef MachODataTypeTypedefHelperCommon<TargetEndianness> Base;
82   typedef typename Base::MachOInt32 MachOIntPtr;
83 };
84
85 template<endianness TargetEndianness>
86 struct MachODataTypeTypedefHelper<MachOType<TargetEndianness, true> > {
87   typedef MachODataTypeTypedefHelperCommon<TargetEndianness> Base;
88   typedef typename Base::MachOInt64 MachOIntPtr;
89 };
90
91 #define LLVM_MACHO_IMPORT_TYPES(MachOT, E, B)                        \
92 LLVM_MACHOB_IMPORT_TYPES(E)                                          \
93 typedef typename                                                     \
94   MachODataTypeTypedefHelper <MachOT<E, B> >::MachOIntPtr MachOIntPtr;
95
96 namespace MachOFormat {
97   struct SectionBase {
98     char Name[16];
99     char SegmentName[16];
100   };
101
102   template<class MachOT>
103   struct Section;
104
105   template<endianness TargetEndianness>
106   struct Section<MachOType<TargetEndianness, false> > {
107     LLVM_MACHOB_IMPORT_TYPES(TargetEndianness)
108     char Name[16];
109     char SegmentName[16];
110     MachOInt32 Address;
111     MachOInt32 Size;
112     MachOInt32 Offset;
113     MachOInt32 Align;
114     MachOInt32 RelocationTableOffset;
115     MachOInt32 NumRelocationTableEntries;
116     MachOInt32 Flags;
117     MachOInt32 Reserved1;
118     MachOInt32 Reserved2;
119   };
120
121   template<endianness TargetEndianness>
122   struct Section<MachOType<TargetEndianness, true> > {
123     LLVM_MACHOB_IMPORT_TYPES(TargetEndianness)
124     char Name[16];
125     char SegmentName[16];
126     MachOInt64 Address;
127     MachOInt64 Size;
128     MachOInt32 Offset;
129     MachOInt32 Align;
130     MachOInt32 RelocationTableOffset;
131     MachOInt32 NumRelocationTableEntries;
132     MachOInt32 Flags;
133     MachOInt32 Reserved1;
134     MachOInt32 Reserved2;
135     MachOInt32 Reserved3;
136   };
137
138   struct MachOInt24 {
139     uint8_t bytes[3];
140     operator uint32_t() const {
141       return (bytes[2] << 24) | (bytes[1] << 16) | bytes[0];
142     }
143   };
144
145   template<endianness TargetEndianness>
146   struct RelocationEntry;
147
148   template<>
149   struct RelocationEntry<support::little> {
150     LLVM_MACHOB_IMPORT_TYPES(support::little)
151     MachOInt32 Address;
152     MachOInt24 SymbolNum;
153     uint8_t Bits;
154
155     unsigned getPCRel() const {
156       return Bits & 0x1;
157     }
158     unsigned getLength() const {
159       return (Bits >> 1) & 0x3;
160     }
161     unsigned getExternal() const {
162       return (Bits >> 3) & 0x1;
163     }
164     unsigned getType() const {
165       return Bits >> 4;
166     }
167   };
168
169   template<>
170   struct RelocationEntry<support::big> {
171     LLVM_MACHOB_IMPORT_TYPES(support::big)
172     MachOInt32 Address;
173     MachOInt24 SymbolNum;
174     uint8_t Bits;
175
176     unsigned getType() const {
177       return Bits &0xf;
178     }
179     unsigned getExternal() const {
180       return (Bits >> 4) & 0x1;
181     }
182     unsigned getLength() const {
183       return (Bits >> 5) & 0x3;
184     }
185     unsigned getPCRel() const {
186       return Bits >> 7;
187     }
188   };
189
190   template<endianness TargetEndianness>
191   struct ScatteredRelocationEntry;
192
193   template<>
194   struct ScatteredRelocationEntry<support::little> {
195     LLVM_MACHOB_IMPORT_TYPES(support::little)
196     MachOInt24 Address;
197     uint8_t Bits;
198     MachOInt32 Value;
199
200     unsigned getType() const {
201       return Bits & 0xf;
202     }
203     unsigned getLength() const {
204       return (Bits >> 4) & 0x3;
205     }
206     unsigned getPCRel() const {
207       return (Bits >> 6) & 0x1;
208     }
209     unsigned getScattered() const {
210       return Bits >> 7;
211     }
212   };
213
214   template<>
215   struct ScatteredRelocationEntry<support::big> {
216     LLVM_MACHOB_IMPORT_TYPES(support::big)
217     uint8_t Bits;
218     unsigned getType() const {
219       return Bits & 0xf;
220     }
221     unsigned getLength() const {
222       return (Bits >> 4) & 0x3;
223     }
224     unsigned getPCRel() const {
225       return (Bits >> 6) & 0x1;
226     }
227     unsigned getScattered() const {
228       return Bits >> 7;
229     }
230     MachOInt24 Address;
231     MachOInt32 Value;
232   };
233
234   template<endianness TargetEndianness>
235   struct SymbolTableEntryBase {
236     LLVM_MACHOB_IMPORT_TYPES(TargetEndianness)
237     MachOInt32 StringIndex;
238     uint8_t Type;
239     uint8_t SectionIndex;
240     MachOInt16 Flags;
241   };
242
243   template<class MachOT>
244   struct SymbolTableEntry;
245
246   template<endianness TargetEndianness, bool Is64Bits>
247   struct SymbolTableEntry<MachOType<TargetEndianness, Is64Bits> > {
248     LLVM_MACHO_IMPORT_TYPES(MachOType, TargetEndianness, Is64Bits)
249     MachOInt32 StringIndex;
250     uint8_t Type;
251     uint8_t SectionIndex;
252     MachOInt16 Flags;
253     MachOIntPtr Value;
254   };
255
256   template<endianness TargetEndianness>
257   struct LoadCommand {
258     LLVM_MACHOB_IMPORT_TYPES(TargetEndianness)
259     MachOInt32 Type;
260     MachOInt32 Size;
261   };
262
263   template<endianness TargetEndianness>
264   struct SymtabLoadCommand {
265     LLVM_MACHOB_IMPORT_TYPES(TargetEndianness)
266     MachOInt32 Type;
267     MachOInt32 Size;
268     MachOInt32 SymbolTableOffset;
269     MachOInt32 NumSymbolTableEntries;
270     MachOInt32 StringTableOffset;
271     MachOInt32 StringTableSize;
272   };
273
274   template<class MachOT>
275   struct SegmentLoadCommand;
276
277   template<endianness TargetEndianness, bool Is64Bits>
278   struct SegmentLoadCommand<MachOType<TargetEndianness, Is64Bits> > {
279     LLVM_MACHO_IMPORT_TYPES(MachOType, TargetEndianness, Is64Bits)
280     MachOInt32 Type;
281     MachOInt32 Size;
282     char Name[16];
283     MachOIntPtr VMAddress;
284     MachOIntPtr VMSize;
285     MachOIntPtr FileOffset;
286     MachOIntPtr FileSize;
287     MachOInt32 MaxVMProtection;
288     MachOInt32 InitialVMProtection;
289     MachOInt32 NumSections;
290     MachOInt32 Flags;
291   };
292
293   template<endianness TargetEndianness>
294   struct LinkeditDataLoadCommand {
295     LLVM_MACHOB_IMPORT_TYPES(TargetEndianness)
296     MachOInt32 Type;
297     MachOInt32 Size;
298     MachOInt32 DataOffset;
299     MachOInt32 DataSize;
300   };
301
302   template<endianness TargetEndianness>
303   struct Header {
304     LLVM_MACHOB_IMPORT_TYPES(TargetEndianness)
305     MachOInt32 Magic;
306     MachOInt32 CPUType;
307     MachOInt32 CPUSubtype;
308     MachOInt32 FileType;
309     MachOInt32 NumLoadCommands;
310     MachOInt32 SizeOfLoadCommands;
311     MachOInt32 Flags;
312   };
313 }
314
315 class MachOObjectFileBase : public ObjectFile {
316 public:
317   typedef MachOFormat::SectionBase SectionBase;
318
319   MachOObjectFileBase(MemoryBuffer *Object, bool IsLittleEndian, bool Is64Bits,
320                       error_code &ec);
321
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;
326
327   virtual uint8_t getBytesInAddress() const;
328   virtual StringRef getLoadName() const;
329
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;
334
335   static inline bool classof(const Binary *v) {
336     return v->isMachO();
337   }
338
339 protected:
340   StringRef parseSegmentOrSectionName(const char *P) const;
341
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,
346                                                    bool &Res) const;
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;
350
351   virtual error_code getRelocationNext(DataRefImpl Rel,
352                                        RelocationRef &Res) const;
353
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,
357                                                  int64_t &Res) const;
358
359   std::size_t getSectionIndex(DataRefImpl Sec) const;
360
361   typedef SmallVector<DataRefImpl, 1> SectionList;
362   SectionList Sections;
363 };
364
365 template<endianness TargetEndianness>
366 class MachOObjectFileMiddle : public MachOObjectFileBase {
367 public:
368
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;
379
380   MachOObjectFileMiddle(MemoryBuffer *Object, bool Is64Bits, error_code &ec);
381
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;
389
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;
396
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;
401
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;
406
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;
421
422   static bool classof(const Binary *v);
423
424 private:
425   // Helper to advance a section or symbol iterator multiple increments at a
426   // time.
427   template<class T>
428   static error_code advance(T &it, size_t Val);
429
430   template<class T>
431   static void advanceTo(T &it, size_t Val);
432 };
433
434 template<class MachOT>
435 struct MachOObjectFileHelperCommon;
436
437 template<endianness TargetEndianness, bool Is64Bits>
438 struct MachOObjectFileHelperCommon<MachOType<TargetEndianness, Is64Bits> > {
439   typedef
440     MachOFormat::SegmentLoadCommand<MachOType<TargetEndianness, Is64Bits> >
441     SegmentLoadCommand;
442   typedef MachOFormat::SymbolTableEntry<MachOType<TargetEndianness, Is64Bits> >
443     SymbolTableEntry;
444   typedef MachOFormat::Section<MachOType<TargetEndianness, Is64Bits> > Section;
445 };
446
447 template<class MachOT>
448 struct MachOObjectFileHelper;
449
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;
454 };
455
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;
460 };
461
462 template<class MachOT>
463 class MachOObjectFile : public MachOObjectFileMiddle<MachOT::TargetEndianness> {
464 public:
465   static const endianness TargetEndianness = MachOT::TargetEndianness;
466   static const bool Is64Bits = MachOT::Is64Bits;
467
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;
473
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;
479
480   MachOObjectFile(MemoryBuffer *Object, error_code &ec);
481   static bool classof(const Binary *v);
482
483   const Section *getSection(DataRefImpl DRI) const;
484   const SymbolTableEntry *getSymbolTableEntry(DataRefImpl DRI) const;
485   const RelocationEntry *getRelocation(DataRefImpl Rel) const;
486
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,
505                                            bool &Result) const;
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;
511 };
512
513 typedef MachOObjectFileMiddle<support::little> MachOObjectFileLE;
514 typedef MachOObjectFileMiddle<support::big> MachOObjectFileBE;
515
516 typedef MachOObjectFile<MachOType<support::little, false> >
517   MachOObjectFileLE32;
518 typedef MachOObjectFile<MachOType<support::big, false> >
519   MachOObjectFileBE32;
520 typedef MachOObjectFile<MachOType<support::little, true> >
521   MachOObjectFileLE64;
522 typedef MachOObjectFile<MachOType<support::big, true> >
523   MachOObjectFileBE64;
524
525 template<endianness TargetEndianness>
526 MachOObjectFileMiddle<TargetEndianness>::MachOObjectFileMiddle(MemoryBuffer *O,
527                                                                bool Is64Bits,
528                                                                error_code &ec) :
529   MachOObjectFileBase(O, TargetEndianness == support::little, Is64Bits, ec) {
530 }
531
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);
537
538   unsigned Index = DRI.d.b;
539
540   unsigned SymbolTableEntrySize = is64Bit() ?
541     sizeof(MachOObjectFileLE64::SymbolTableEntry) :
542     sizeof(MachOObjectFileLE32::SymbolTableEntry);
543
544   uint64_t Offset = S->SymbolTableOffset + Index * SymbolTableEntrySize;
545   StringRef Data = getData(Offset, SymbolTableEntrySize);
546   return reinterpret_cast<const SymbolTableEntryBase*>(Data.data());
547 }
548
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());
554 }
555
556 template<endianness E>
557 const typename MachOObjectFileMiddle<E>::LoadCommand *
558 MachOObjectFileMiddle<E>::getLoadCommandInfo(unsigned Index) const {
559   assert(Index < getHeader()->NumLoadCommands);
560   uint64_t Offset;
561   uint64_t NewOffset = getHeaderSize();
562   const LoadCommand *Load;
563   unsigned I = 0;
564   do {
565     Offset = NewOffset;
566     StringRef Data = getData(Offset, sizeof(MachOObjectFileLE::LoadCommand));
567     Load = reinterpret_cast<const LoadCommand*>(Data.data());
568     NewOffset = Offset + Load->Size;
569     ++I;
570   } while (I != Index + 1);
571
572   return reinterpret_cast<const LoadCommand*>(Load);
573 }
574
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);
581
582   const MachOObjectFile<MachOType<E, false> > *O =
583     cast<MachOObjectFile<MachOType<E, false> > >(this);
584   return O->getRelocation(Rel);
585 }
586
587 template<endianness E>
588 bool
589 MachOObjectFileMiddle<E>::isRelocationScattered(const RelocationEntry *RE)
590                                                                          const {
591   if (this->getCPUType() == llvm::MachO::CPUTypeX86_64)
592     return false;
593   return RE->Address & macho::RF_Scattered;
594 }
595
596 template<endianness E>
597 bool
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();
604   }
605   return RE->getPCRel();
606 }
607
608 template<endianness E>
609 unsigned
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();
616   }
617   return RE->getLength();
618 }
619
620 template<endianness E>
621 unsigned
622 MachOObjectFileMiddle<E>::getRelocationTypeImpl(const RelocationEntry *RE)
623                                                                          const {
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();
629   }
630   return RE->getType();
631 }
632
633 // Helper to advance a section or symbol iterator multiple increments at a time.
634 template<endianness E>
635 template<class T>
636 error_code MachOObjectFileMiddle<E>::advance(T &it, size_t Val) {
637   error_code ec;
638   while (Val--) {
639     it.increment(ec);
640   }
641   return ec;
642 }
643
644 template<endianness E>
645 template<class T>
646 void MachOObjectFileMiddle<E>::advanceTo(T &it, size_t Val) {
647   if (error_code ec = advance(it, Val))
648     report_fatal_error(ec.message());
649 }
650
651 template<endianness E>
652 void
653 MachOObjectFileMiddle<E>::printRelocationTargetName(const RelocationEntry *RE,
654                                                 raw_string_ostream &fmt) const {
655   bool IsScattered = isRelocationScattered(RE);
656
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.
661   if (IsScattered) {
662     uint32_t Val = RE->SymbolNum;
663
664     error_code ec;
665     for (symbol_iterator SI = begin_symbols(), SE = end_symbols(); SI != SE;
666         SI.increment(ec)) {
667       if (ec) report_fatal_error(ec.message());
668
669       uint64_t Addr;
670       StringRef Name;
671
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());
677       fmt << Name;
678       return;
679     }
680
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;
684          SI.increment(ec)) {
685       if (ec) report_fatal_error(ec.message());
686
687       uint64_t Addr;
688       StringRef Name;
689
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());
695       fmt << Name;
696       return;
697     }
698
699     fmt << format("0x%x", Val);
700     return;
701   }
702
703   StringRef S;
704   bool isExtern = RE->getExternal();
705   uint64_t Val = RE->Address;
706
707   if (isExtern) {
708     symbol_iterator SI = begin_symbols();
709     advanceTo(SI, Val);
710     SI->getName(S);
711   } else {
712     section_iterator SI = begin_sections();
713     advanceTo(SI, Val);
714     SI->getName(S);
715   }
716
717   fmt << S;
718 }
719
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));
725
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);
732
733   uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + DRI.d.b * SectionSize;
734   return reinterpret_cast<const SectionBase*>(SectionAddr);
735 }
736
737 template<endianness E>
738 unsigned MachOObjectFileMiddle<E>::getCPUType() const {
739   return getHeader()->CPUType;
740 }
741
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)
751         return;
752     }
753
754     DRI.d.a++;
755     DRI.d.b = 0;
756   }
757 }
758
759 template<endianness E>
760 StringRef
761 MachOObjectFileMiddle<E>::getSectionFinalSegmentName(DataRefImpl Sec) const {
762   ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
763   return parseSegmentOrSectionName(Raw.data());
764 }
765
766 template<endianness E>
767 ArrayRef<char>
768 MachOObjectFileMiddle<E>::getSectionRawName(DataRefImpl Sec) const {
769   const SectionBase *Base = getSectionBase(Sec);
770   return ArrayRef<char>(Base->Name);
771 }
772
773 template<endianness E>
774 ArrayRef<char>
775 MachOObjectFileMiddle<E>::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
776   const SectionBase *Base = getSectionBase(Sec);
777   return ArrayRef<char>(Base->SegmentName);
778 }
779
780 template<endianness E>
781 error_code MachOObjectFileMiddle<E>::getSymbolFlags(DataRefImpl DRI,
782                                                     uint32_t &Result) const {
783   const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(DRI);
784
785   uint8_t MachOType = Entry->Type;
786   uint16_t MachOFlags = Entry->Flags;
787
788   // TODO: Correctly set SF_ThreadLocal
789   Result = SymbolRef::SF_None;
790
791   if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
792     Result |= SymbolRef::SF_Undefined;
793
794   if (MachOFlags & macho::STF_StabsEntryMask)
795     Result |= SymbolRef::SF_FormatSpecific;
796
797   if (MachOType & MachO::NlistMaskExternal) {
798     Result |= SymbolRef::SF_Global;
799     if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
800       Result |= SymbolRef::SF_Common;
801   }
802
803   if (MachOFlags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef))
804     Result |= SymbolRef::SF_Weak;
805
806   if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeAbsolute)
807     Result |= SymbolRef::SF_Absolute;
808
809   return object_error::success;
810 }
811
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;
817
818   Res = SymbolRef::ST_Other;
819
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;
824   }
825
826   switch (n_type & MachO::NlistMaskType) {
827     case MachO::NListTypeUndefined :
828       Res = SymbolRef::ST_Unknown;
829       break;
830     case MachO::NListTypeSection :
831       Res = SymbolRef::ST_Function;
832       break;
833   }
834   return object_error::success;
835 }
836
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;
847 }
848
849 template<endianness E>
850 error_code
851 MachOObjectFileMiddle<E>::getSymbolSection(DataRefImpl Symb,
852                                            section_iterator &Res) const {
853   const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(Symb);
854   uint8_t index = Entry->SectionIndex;
855
856   if (index == 0)
857     Res = end_sections();
858   else
859     Res = section_iterator(SectionRef(Sections[index-1], this));
860
861   return object_error::success;
862 }
863
864
865 template<endianness E>
866 error_code MachOObjectFileMiddle<E>::getSymbolNMTypeChar(DataRefImpl Symb,
867                                                          char &Res) const {
868   const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(Symb);
869   uint8_t Type = Entry->Type;
870   uint16_t Flags = Entry->Flags;
871
872   char Char;
873   switch (Type & macho::STF_TypeMask) {
874     case macho::STT_Undefined:
875       Char = 'u';
876       break;
877     case macho::STT_Absolute:
878     case macho::STT_Section:
879       Char = 's';
880       break;
881     default:
882       Char = '?';
883       break;
884   }
885
886   if (Flags & (macho::STF_External | macho::STF_PrivateExtern))
887     Char = toupper(static_cast<unsigned char>(Char));
888   Res = Char;
889   return object_error::success;
890 }
891
892 template<endianness E>
893 error_code
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;
899 }
900
901 template<endianness E>
902 error_code MachOObjectFileMiddle<E>::getSymbolNext(DataRefImpl Symb,
903                                                      SymbolRef &Res) const {
904   Symb.d.b++;
905   moveToNextSymbol(Symb);
906   Res = SymbolRef(Symb, this);
907   return object_error::success;
908 }
909
910 template<endianness E>
911 symbol_iterator MachOObjectFileMiddle<E>::begin_symbols() const {
912   // DRI.d.a = segment number; DRI.d.b = symbol index.
913   DataRefImpl DRI;
914   moveToNextSymbol(DRI);
915   return symbol_iterator(SymbolRef(DRI, this));
916 }
917
918 template<endianness E>
919 unsigned MachOObjectFileMiddle<E>::getArch() const {
920   switch (getCPUType()) {
921   case llvm::MachO::CPUTypeI386:
922     return Triple::x86;
923   case llvm::MachO::CPUTypeX86_64:
924     return Triple::x86_64;
925   case llvm::MachO::CPUTypeARM:
926     return Triple::arm;
927   case llvm::MachO::CPUTypePowerPC:
928     return Triple::ppc;
929   case llvm::MachO::CPUTypePowerPC64:
930     return Triple::ppc64;
931   default:
932     return Triple::UnknownArch;
933   }
934 }
935
936 template<endianness E>
937 StringRef MachOObjectFileMiddle<E>::getFileFormatName() const {
938   unsigned CPUType = getCPUType();
939   if (!is64Bit()) {
940     switch (CPUType) {
941     case llvm::MachO::CPUTypeI386:
942       return "Mach-O 32-bit i386";
943     case llvm::MachO::CPUTypeARM:
944       return "Mach-O arm";
945     case llvm::MachO::CPUTypePowerPC:
946       return "Mach-O 32-bit ppc";
947     default:
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";
951     }
952   }
953
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?");
958
959   switch (CPUType) {
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";
964   default:
965     return "Mach-O 64-bit unknown";
966   }
967 }
968
969 template<endianness E>
970 symbol_iterator MachOObjectFileMiddle<E>::end_symbols() const {
971   DataRefImpl DRI;
972   DRI.d.a = getHeader()->NumLoadCommands;
973   return symbol_iterator(SymbolRef(DRI, this));
974 }
975
976 template<endianness E>
977 section_iterator MachOObjectFileMiddle<E>::end_sections() const {
978   DataRefImpl DRI;
979   DRI.d.a = getHeader()->NumLoadCommands;
980   return section_iterator(SectionRef(DRI, this));
981 }
982
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);
987 }
988
989 template<class MachOT>
990 MachOObjectFile<MachOT>::MachOObjectFile(MemoryBuffer *Object,
991                                          error_code &ec) :
992   MachOObjectFileMiddle<TargetEndianness>(Object, Is64Bits, ec) {
993   DataRefImpl DRI;
994   moveToNextSection(DRI);
995   uint32_t LoadCommandCount = this->getHeader()->NumLoadCommands;
996   while (DRI.d.a < LoadCommandCount) {
997     this->Sections.push_back(DRI);
998     DRI.d.b++;
999     moveToNextSection(DRI);
1000   }
1001 }
1002
1003 template<class MachOT>
1004 bool MachOObjectFile<MachOT>::classof(const Binary *v) {
1005   return v->getType() ==
1006     Base::getMachOType(TargetEndianness == support::little, Is64Bits);
1007 }
1008
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);
1014 }
1015
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);
1021 }
1022
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());
1031 }
1032
1033 template<class MachOT>
1034 error_code
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;
1040 }
1041
1042 template<class MachOT>
1043 error_code
1044 MachOObjectFile<MachOT>::getSectionSize(DataRefImpl Sec,
1045                                         uint64_t &Res) const {
1046   const Section *Sect = getSection(Sec);
1047   Res = Sect->Size;
1048   return object_error::success;
1049 }
1050
1051 template<class MachOT>
1052 error_code
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;
1058 }
1059
1060 template<class MachOT>
1061 error_code
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;
1067 }
1068
1069 template<class MachOT>
1070 error_code
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;
1075 }
1076
1077 template<class MachOT>
1078 error_code
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;
1085 }
1086
1087 template<class MachOT>
1088 relocation_iterator
1089 MachOObjectFile<MachOT>::getSectionRelEnd(DataRefImpl Sec) const {
1090   const Section *Sect = getSection(Sec);
1091   uint32_t LastReloc = Sect->NumRelocationTableEntries;
1092   DataRefImpl Ret;
1093   Ret.d.a = LastReloc;
1094   Ret.d.b = this->getSectionIndex(Sec);
1095   return relocation_iterator(RelocationRef(Ret, this));
1096 }
1097
1098 template<class MachOT>
1099 error_code
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);
1105
1106   uint64_t RelAddr;
1107   if (this->isRelocationScattered(RE))
1108     RelAddr = RE->Address & 0xFFFFFF;
1109   else
1110     RelAddr = RE->Address;
1111
1112   Res = SectAddress + RelAddr;
1113   return object_error::success;
1114 }
1115
1116 template<class MachOT>
1117 error_code
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;
1123   else
1124     Res = RE->Address;
1125   return object_error::success;
1126 }
1127
1128 template<class MachOT>
1129 error_code
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();
1135
1136   DataRefImpl Sym;
1137   this->moveToNextSymbol(Sym);
1138   if (isExtern) {
1139     for (unsigned i = 0; i < SymbolIdx; i++) {
1140       Sym.d.b++;
1141       this->moveToNextSymbol(Sym);
1142       assert(Sym.d.a < this->getHeader()->NumLoadCommands &&
1143              "Relocation symbol index out of range!");
1144     }
1145   }
1146   Res = SymbolRef(Sym, this);
1147   return object_error::success;
1148 }
1149
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;
1156 }
1157
1158 template<class MachOT>
1159 error_code
1160 MachOObjectFile<MachOT>::getRelocationTypeName(DataRefImpl Rel,
1161                                           SmallVectorImpl<char> &Result) const {
1162     // TODO: Support scattered relocations.
1163   StringRef res;
1164   const RelocationEntry *RE = getRelocation(Rel);
1165
1166   unsigned Arch = this->getArch();
1167
1168   unsigned r_type = this->getRelocationTypeImpl(RE);
1169
1170   switch (Arch) {
1171     case Triple::x86: {
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" };
1179
1180       if (r_type > 6)
1181         res = "Unknown";
1182       else
1183         res = Table[r_type];
1184       break;
1185     }
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",
1192         "X86_64_RELOC_GOT",
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" };
1198
1199       if (r_type > 9)
1200         res = "Unknown";
1201       else
1202         res = Table[r_type];
1203       break;
1204     }
1205     case Triple::arm: {
1206       static const char *const Table[] =  {
1207         "ARM_RELOC_VANILLA",
1208         "ARM_RELOC_PAIR",
1209         "ARM_RELOC_SECTDIFF",
1210         "ARM_RELOC_LOCAL_SECTDIFF",
1211         "ARM_RELOC_PB_LA_PTR",
1212         "ARM_RELOC_BR24",
1213         "ARM_THUMB_RELOC_BR22",
1214         "ARM_THUMB_32BIT_BRANCH",
1215         "ARM_RELOC_HALF",
1216         "ARM_RELOC_HALF_SECTDIFF" };
1217
1218       if (r_type > 9)
1219         res = "Unknown";
1220       else
1221         res = Table[r_type];
1222       break;
1223     }
1224     case Triple::ppc: {
1225       static const char *const Table[] =  {
1226         "PPC_RELOC_VANILLA",
1227         "PPC_RELOC_PAIR",
1228         "PPC_RELOC_BR14",
1229         "PPC_RELOC_BR24",
1230         "PPC_RELOC_HI16",
1231         "PPC_RELOC_LO16",
1232         "PPC_RELOC_HA16",
1233         "PPC_RELOC_LO14",
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",
1239         "PPC_RELOC_JBSR",
1240         "PPC_RELOC_LO14_SECTDIFF",
1241         "PPC_RELOC_LOCAL_SECTDIFF" };
1242
1243       res = Table[r_type];
1244       break;
1245     }
1246     case Triple::UnknownArch:
1247       res = "Unknown";
1248       break;
1249   }
1250   Result.append(res.begin(), res.end());
1251   return object_error::success;
1252 }
1253
1254 template<class MachOT>
1255 error_code
1256 MachOObjectFile<MachOT>::getRelocationValueString(DataRefImpl Rel,
1257                                           SmallVectorImpl<char> &Result) const {
1258   const RelocationEntry *RE = getRelocation(Rel);
1259
1260   unsigned Arch = this->getArch();
1261   bool IsScattered = this->isRelocationScattered(RE);
1262
1263   std::string fmtbuf;
1264   raw_string_ostream fmt(fmtbuf);
1265
1266   unsigned Type = this->getRelocationTypeImpl(RE);
1267   bool IsPCRel = this->isRelocationPCRel(RE);
1268
1269   // Determine any addends that should be displayed with the relocation.
1270   // These require decoding the relocation type, which is triple-specific.
1271
1272   // X86_64 has entirely custom relocation types.
1273   if (Arch == Triple::x86_64) {
1274     bool isPCRel = RE->getPCRel();
1275
1276     switch (Type) {
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);
1280         fmt << "@GOT";
1281         if (isPCRel) fmt << "PCREL";
1282         break;
1283       }
1284       case macho::RIT_X86_64_Subtractor: { // X86_64_RELOC_SUBTRACTOR
1285         DataRefImpl RelNext = Rel;
1286         RelNext.d.a++;
1287         const RelocationEntry *RENext = getRelocation(RelNext);
1288
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();
1293         if (RType != 0)
1294           report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
1295                              "X86_64_RELOC_SUBTRACTOR.");
1296
1297         // The X86_64_RELOC_UNSIGNED contains the minuend symbol,
1298         // X86_64_SUBTRACTOR contains to the subtrahend.
1299         this->printRelocationTargetName(RENext, fmt);
1300         fmt << "-";
1301         this->printRelocationTargetName(RE, fmt);
1302         break;
1303       }
1304       case macho::RIT_X86_64_TLV:
1305         this->printRelocationTargetName(RE, fmt);
1306         fmt << "@TLV";
1307         if (isPCRel) fmt << "P";
1308         break;
1309       case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1
1310         this->printRelocationTargetName(RE, fmt);
1311         fmt << "-1";
1312         break;
1313       case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2
1314         this->printRelocationTargetName(RE, fmt);
1315         fmt << "-2";
1316         break;
1317       case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4
1318         this->printRelocationTargetName(RE, fmt);
1319         fmt << "-4";
1320         break;
1321       default:
1322         this->printRelocationTargetName(RE, fmt);
1323         break;
1324     }
1325   // X86 and ARM share some relocation types in common.
1326   } else if (Arch == Triple::x86 || Arch == Triple::arm) {
1327     // Generic relocation types...
1328     switch (Type) {
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;
1333         RelNext.d.a++;
1334         const RelocationEntry *RENext = getRelocation(RelNext);
1335
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);
1340         unsigned RType;
1341         if (isNextScattered)
1342           RType = (RENext->Address >> 24) & 0xF;
1343         else
1344           RType = RENext->getType();
1345         if (RType != 1)
1346           report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1347                              "GENERIC_RELOC_SECTDIFF.");
1348
1349         this->printRelocationTargetName(RE, fmt);
1350         fmt << "-";
1351         this->printRelocationTargetName(RENext, fmt);
1352         break;
1353       }
1354     }
1355
1356     if (Arch == Triple::x86) {
1357       // All X86 relocations that need special printing were already
1358       // handled in the generic code.
1359       switch (Type) {
1360         case macho::RIT_Generic_LocalDifference:{// GENERIC_RELOC_LOCAL_SECTDIFF
1361           DataRefImpl RelNext = Rel;
1362           RelNext.d.a++;
1363           const RelocationEntry *RENext = getRelocation(RelNext);
1364
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);
1369           unsigned RType;
1370           if (isNextScattered)
1371             RType = (RENext->Address >> 24) & 0xF;
1372           else
1373             RType = RENext->getType();
1374           if (RType != 1)
1375             report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1376                                "GENERIC_RELOC_LOCAL_SECTDIFF.");
1377
1378           this->printRelocationTargetName(RE, fmt);
1379           fmt << "-";
1380           this->printRelocationTargetName(RENext, fmt);
1381           break;
1382         }
1383         case macho::RIT_Generic_TLV: {
1384           this->printRelocationTargetName(RE, fmt);
1385           fmt << "@TLV";
1386           if (IsPCRel) fmt << "P";
1387           break;
1388         }
1389         default:
1390           this->printRelocationTargetName(RE, fmt);
1391       }
1392     } else { // ARM-specific relocations
1393       switch (Type) {
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.
1398           bool isUpper;
1399           if (IsScattered)
1400             isUpper = (RE->Address >> 28) & 1;
1401           else
1402             isUpper = (RE->getLength() >> 1) & 1;
1403
1404           if (isUpper)
1405             fmt << ":upper16:(";
1406           else
1407             fmt << ":lower16:(";
1408           this->printRelocationTargetName(RE, fmt);
1409
1410           DataRefImpl RelNext = Rel;
1411           RelNext.d.a++;
1412           const RelocationEntry *RENext = getRelocation(RelNext);
1413
1414           // ARM half relocs must be followed by a relocation of type
1415           // ARM_RELOC_PAIR.
1416           bool isNextScattered = (Arch != Triple::x86_64) &&
1417                                  (RENext->Address & macho::RF_Scattered);
1418           unsigned RType;
1419           if (isNextScattered)
1420             RType = (RENext->Address >> 24) & 0xF;
1421           else
1422             RType = RENext->getType();
1423
1424           if (RType != 1)
1425             report_fatal_error("Expected ARM_RELOC_PAIR after "
1426                                "GENERIC_RELOC_HALF");
1427
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.
1432
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) {
1436             fmt << "-";
1437             this->printRelocationTargetName(RENext, fmt);
1438           }
1439
1440           fmt << ")";
1441           break;
1442         }
1443         default: {
1444           this->printRelocationTargetName(RE, fmt);
1445         }
1446       }
1447     }
1448   } else
1449     this->printRelocationTargetName(RE, fmt);
1450
1451   fmt.flush();
1452   Result.append(fmtbuf.begin(), fmtbuf.end());
1453   return object_error::success;
1454 }
1455
1456 template<class MachOT>
1457 error_code
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);
1463
1464   Result = false;
1465
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;
1475       RelPrev.d.a--;
1476       const RelocationEntry *REPrev = this->getRelocation(RelPrev);
1477
1478       unsigned PrevType = REPrev->getType();
1479
1480       if (PrevType == macho::RIT_X86_64_Subtractor) Result = true;
1481     }
1482   }
1483
1484   return object_error::success;
1485 }
1486
1487 template<class MachOT>
1488 error_code
1489 MachOObjectFile<MachOT>::getSymbolFileOffset(DataRefImpl Symb,
1490                                              uint64_t &Res) const {
1491   const SymbolTableEntry *Entry = getSymbolTableEntry(Symb);
1492   Res = Entry->Value;
1493   if (Entry->SectionIndex) {
1494     const Section *Sec =
1495       this->getSection(this->Sections[Entry->SectionIndex-1]);
1496     Res += Sec->Offset - Sec->Address;
1497   }
1498
1499   return object_error::success;
1500 }
1501
1502 template<class MachOT>
1503 error_code
1504 MachOObjectFile<MachOT>::sectionContainsSymbol(DataRefImpl Sec,
1505                                                DataRefImpl Symb,
1506                                                bool &Result) const {
1507   SymbolRef::Type ST;
1508   this->getSymbolType(Symb, ST);
1509   if (ST == SymbolRef::ST_Unknown) {
1510     Result = false;
1511     return object_error::success;
1512   }
1513
1514   uint64_t SectBegin, SectEnd;
1515   getSectionAddress(Sec, SectBegin);
1516   getSectionSize(Sec, SectEnd);
1517   SectEnd += SectBegin;
1518
1519   const SymbolTableEntry *Entry = getSymbolTableEntry(Symb);
1520   uint64_t SymAddr= Entry->Value;
1521   Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
1522
1523   return object_error::success;
1524 }
1525
1526 template<class MachOT>
1527 error_code MachOObjectFile<MachOT>::getSymbolAddress(DataRefImpl Symb,
1528                                                      uint64_t &Res) const {
1529   const SymbolTableEntry *Entry = getSymbolTableEntry(Symb);
1530   Res = Entry->Value;
1531   return object_error::success;
1532 }
1533
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;
1541
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;
1550     else
1551       Result = UnknownAddressOrSize;
1552     return object_error::success;
1553   }
1554   // Unfortunately symbols are unsorted so we need to touch all
1555   // symbols from load command
1556   DRI.d.b = 0;
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;
1565     }
1566     DRI.d.b++;
1567   }
1568   if (!EndOffset) {
1569     uint64_t Size;
1570     this->getSectionSize(this->Sections[SectionIndex-1], Size);
1571     this->getSectionAddress(this->Sections[SectionIndex-1], EndOffset);
1572     EndOffset += Size;
1573   }
1574   Result = EndOffset - BeginOffset;
1575   return object_error::success;
1576 }
1577
1578 template<class MachOT>
1579 error_code MachOObjectFile<MachOT>::getSectionNext(DataRefImpl Sec,
1580                                                    SectionRef &Res) const {
1581   Sec.d.b++;
1582   moveToNextSection(Sec);
1583   Res = SectionRef(Sec, this);
1584   return object_error::success;
1585 }
1586
1587 template<class MachOT>
1588 section_iterator MachOObjectFile<MachOT>::begin_sections() const {
1589   DataRefImpl DRI;
1590   moveToNextSection(DRI);
1591   return section_iterator(SectionRef(DRI, this));
1592 }
1593
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)
1603         return;
1604     }
1605
1606     DRI.d.a++;
1607     DRI.d.b = 0;
1608   }
1609 }
1610
1611 }
1612 }
1613
1614 #endif
1615