Add typenames to see if bot goes green.
[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_TYPENAME(E)                                 \
71 typedef typename MachODataTypeTypedefHelperCommon<E>::MachOInt16 MachOInt16; \
72 typedef typename MachODataTypeTypedefHelperCommon<E>::MachOInt32 MachOInt32; \
73 typedef typename MachODataTypeTypedefHelperCommon<E>::MachOInt64 MachOInt64; \
74 typedef typename MachODataTypeTypedefHelperCommon<E>::MachOInt24 MachOInt24;
75
76 #define LLVM_MACHOB_IMPORT_TYPES(E)                                          \
77 typedef MachODataTypeTypedefHelperCommon<E>::MachOInt16 MachOInt16; \
78 typedef MachODataTypeTypedefHelperCommon<E>::MachOInt32 MachOInt32; \
79 typedef MachODataTypeTypedefHelperCommon<E>::MachOInt64 MachOInt64; \
80 typedef MachODataTypeTypedefHelperCommon<E>::MachOInt24 MachOInt24;
81
82 template<class MachOT>
83 struct MachODataTypeTypedefHelper;
84
85 template<endianness TargetEndianness>
86 struct MachODataTypeTypedefHelper<MachOType<TargetEndianness, false> > {
87   typedef MachODataTypeTypedefHelperCommon<TargetEndianness> Base;
88   typedef typename Base::MachOInt32 MachOIntPtr;
89 };
90
91 template<endianness TargetEndianness>
92 struct MachODataTypeTypedefHelper<MachOType<TargetEndianness, true> > {
93   typedef MachODataTypeTypedefHelperCommon<TargetEndianness> Base;
94   typedef typename Base::MachOInt64 MachOIntPtr;
95 };
96
97 #define LLVM_MACHO_IMPORT_TYPES(MachOT, E, B)                        \
98 LLVM_MACHOB_IMPORT_TYPES_TYPENAME(E)                                 \
99 typedef typename                                                     \
100   MachODataTypeTypedefHelper <MachOT<E, B> >::MachOIntPtr MachOIntPtr;
101
102 namespace MachOFormat {
103   struct SectionBase {
104     char Name[16];
105     char SegmentName[16];
106   };
107
108   template<class MachOT>
109   struct Section;
110
111   template<endianness TargetEndianness>
112   struct Section<MachOType<TargetEndianness, false> > {
113     LLVM_MACHOB_IMPORT_TYPES_TYPENAME(TargetEndianness)
114     char Name[16];
115     char SegmentName[16];
116     MachOInt32 Address;
117     MachOInt32 Size;
118     MachOInt32 Offset;
119     MachOInt32 Align;
120     MachOInt32 RelocationTableOffset;
121     MachOInt32 NumRelocationTableEntries;
122     MachOInt32 Flags;
123     MachOInt32 Reserved1;
124     MachOInt32 Reserved2;
125   };
126
127   template<endianness TargetEndianness>
128   struct Section<MachOType<TargetEndianness, true> > {
129     LLVM_MACHOB_IMPORT_TYPES_TYPENAME(TargetEndianness)
130     char Name[16];
131     char SegmentName[16];
132     MachOInt64 Address;
133     MachOInt64 Size;
134     MachOInt32 Offset;
135     MachOInt32 Align;
136     MachOInt32 RelocationTableOffset;
137     MachOInt32 NumRelocationTableEntries;
138     MachOInt32 Flags;
139     MachOInt32 Reserved1;
140     MachOInt32 Reserved2;
141     MachOInt32 Reserved3;
142   };
143
144   struct MachOInt24 {
145     uint8_t bytes[3];
146     operator uint32_t() const {
147       return (bytes[2] << 24) | (bytes[1] << 16) | bytes[0];
148     }
149   };
150
151   template<endianness TargetEndianness>
152   struct RelocationEntry;
153
154   template<>
155   struct RelocationEntry<support::little> {
156     LLVM_MACHOB_IMPORT_TYPES(support::little)
157     MachOInt32 Address;
158     MachOInt24 SymbolNum;
159     uint8_t Bits;
160
161     unsigned getPCRel() const {
162       return Bits & 0x1;
163     }
164     unsigned getLength() const {
165       return (Bits >> 1) & 0x3;
166     }
167     unsigned getExternal() const {
168       return (Bits >> 3) & 0x1;
169     }
170     unsigned getType() const {
171       return Bits >> 4;
172     }
173   };
174
175   template<>
176   struct RelocationEntry<support::big> {
177     LLVM_MACHOB_IMPORT_TYPES(support::big)
178     MachOInt32 Address;
179     MachOInt24 SymbolNum;
180     uint8_t Bits;
181
182     unsigned getType() const {
183       return Bits &0xf;
184     }
185     unsigned getExternal() const {
186       return (Bits >> 4) & 0x1;
187     }
188     unsigned getLength() const {
189       return (Bits >> 5) & 0x3;
190     }
191     unsigned getPCRel() const {
192       return Bits >> 7;
193     }
194   };
195
196   template<endianness TargetEndianness>
197   struct ScatteredRelocationEntry;
198
199   template<>
200   struct ScatteredRelocationEntry<support::little> {
201     LLVM_MACHOB_IMPORT_TYPES(support::little)
202     MachOInt24 Address;
203     uint8_t Bits;
204     MachOInt32 Value;
205
206     unsigned getType() const {
207       return Bits & 0xf;
208     }
209     unsigned getLength() const {
210       return (Bits >> 4) & 0x3;
211     }
212     unsigned getPCRel() const {
213       return (Bits >> 6) & 0x1;
214     }
215     unsigned getScattered() const {
216       return Bits >> 7;
217     }
218   };
219
220   template<>
221   struct ScatteredRelocationEntry<support::big> {
222     LLVM_MACHOB_IMPORT_TYPES(support::big)
223     uint8_t Bits;
224     unsigned getType() const {
225       return Bits & 0xf;
226     }
227     unsigned getLength() const {
228       return (Bits >> 4) & 0x3;
229     }
230     unsigned getPCRel() const {
231       return (Bits >> 6) & 0x1;
232     }
233     unsigned getScattered() const {
234       return Bits >> 7;
235     }
236     MachOInt24 Address;
237     MachOInt32 Value;
238   };
239
240   template<endianness TargetEndianness>
241   struct SymbolTableEntryBase {
242     LLVM_MACHOB_IMPORT_TYPES_TYPENAME(TargetEndianness)
243     MachOInt32 StringIndex;
244     uint8_t Type;
245     uint8_t SectionIndex;
246     MachOInt16 Flags;
247   };
248
249   template<class MachOT>
250   struct SymbolTableEntry;
251
252   template<endianness TargetEndianness, bool Is64Bits>
253   struct SymbolTableEntry<MachOType<TargetEndianness, Is64Bits> > {
254     LLVM_MACHO_IMPORT_TYPES(MachOType, TargetEndianness, Is64Bits)
255     MachOInt32 StringIndex;
256     uint8_t Type;
257     uint8_t SectionIndex;
258     MachOInt16 Flags;
259     MachOIntPtr Value;
260   };
261
262   template<endianness TargetEndianness>
263   struct LoadCommand {
264     LLVM_MACHOB_IMPORT_TYPES_TYPENAME(TargetEndianness)
265     MachOInt32 Type;
266     MachOInt32 Size;
267   };
268
269   template<endianness TargetEndianness>
270   struct SymtabLoadCommand {
271     LLVM_MACHOB_IMPORT_TYPES_TYPENAME(TargetEndianness)
272     MachOInt32 Type;
273     MachOInt32 Size;
274     MachOInt32 SymbolTableOffset;
275     MachOInt32 NumSymbolTableEntries;
276     MachOInt32 StringTableOffset;
277     MachOInt32 StringTableSize;
278   };
279
280   template<class MachOT>
281   struct SegmentLoadCommand;
282
283   template<endianness TargetEndianness, bool Is64Bits>
284   struct SegmentLoadCommand<MachOType<TargetEndianness, Is64Bits> > {
285     LLVM_MACHO_IMPORT_TYPES(MachOType, TargetEndianness, Is64Bits)
286     MachOInt32 Type;
287     MachOInt32 Size;
288     char Name[16];
289     MachOIntPtr VMAddress;
290     MachOIntPtr VMSize;
291     MachOIntPtr FileOffset;
292     MachOIntPtr FileSize;
293     MachOInt32 MaxVMProtection;
294     MachOInt32 InitialVMProtection;
295     MachOInt32 NumSections;
296     MachOInt32 Flags;
297   };
298
299   template<endianness TargetEndianness>
300   struct LinkeditDataLoadCommand {
301     LLVM_MACHOB_IMPORT_TYPES_TYPENAME(TargetEndianness)
302     MachOInt32 Type;
303     MachOInt32 Size;
304     MachOInt32 DataOffset;
305     MachOInt32 DataSize;
306   };
307
308   template<endianness TargetEndianness>
309   struct Header {
310     LLVM_MACHOB_IMPORT_TYPES_TYPENAME(TargetEndianness)
311     MachOInt32 Magic;
312     MachOInt32 CPUType;
313     MachOInt32 CPUSubtype;
314     MachOInt32 FileType;
315     MachOInt32 NumLoadCommands;
316     MachOInt32 SizeOfLoadCommands;
317     MachOInt32 Flags;
318   };
319 }
320
321 class MachOObjectFileBase : public ObjectFile {
322 public:
323   typedef MachOFormat::SectionBase SectionBase;
324
325   MachOObjectFileBase(MemoryBuffer *Object, bool IsLittleEndian, bool Is64Bits,
326                       error_code &ec);
327
328   virtual symbol_iterator begin_dynamic_symbols() const;
329   virtual symbol_iterator end_dynamic_symbols() const;
330   virtual library_iterator begin_libraries_needed() const;
331   virtual library_iterator end_libraries_needed() const;
332
333   virtual uint8_t getBytesInAddress() const;
334   virtual StringRef getLoadName() const;
335
336   bool is64Bit() const;
337   void ReadULEB128s(uint64_t Index, SmallVectorImpl<uint64_t> &Out) const;
338   unsigned getHeaderSize() const;
339   StringRef getData(size_t Offset, size_t Size) const;
340
341   static inline bool classof(const Binary *v) {
342     return v->isMachO();
343   }
344
345 protected:
346   StringRef parseSegmentOrSectionName(const char *P) const;
347
348   virtual error_code getSymbolValue(DataRefImpl Symb, uint64_t &Val) const;
349   virtual error_code isSectionData(DataRefImpl Sec, bool &Res) const;
350   virtual error_code isSectionBSS(DataRefImpl Sec, bool &Res) const;
351   virtual error_code isSectionRequiredForExecution(DataRefImpl Sec,
352                                                    bool &Res) const;
353   virtual error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const;
354   virtual error_code isSectionReadOnlyData(DataRefImpl Sec, bool &Res) const;
355   virtual relocation_iterator getSectionRelBegin(DataRefImpl Sec) const;
356
357   virtual error_code getRelocationNext(DataRefImpl Rel,
358                                        RelocationRef &Res) const;
359
360   virtual error_code getLibraryNext(DataRefImpl LibData, LibraryRef &Res) const;
361   virtual error_code getLibraryPath(DataRefImpl LibData, StringRef &Res) const;
362   virtual error_code getRelocationAdditionalInfo(DataRefImpl Rel,
363                                                  int64_t &Res) const;
364
365   std::size_t getSectionIndex(DataRefImpl Sec) const;
366
367   typedef SmallVector<DataRefImpl, 1> SectionList;
368   SectionList Sections;
369 };
370
371 template<endianness TargetEndianness>
372 class MachOObjectFileMiddle : public MachOObjectFileBase {
373 public:
374
375   typedef MachOFormat::SymbolTableEntryBase<TargetEndianness>
376     SymbolTableEntryBase;
377   typedef MachOFormat::LinkeditDataLoadCommand<TargetEndianness>
378     LinkeditDataLoadCommand;
379   typedef MachOFormat::Header<TargetEndianness> Header;
380   typedef MachOFormat::SymtabLoadCommand<TargetEndianness> SymtabLoadCommand;
381   typedef MachOFormat::RelocationEntry<TargetEndianness> RelocationEntry;
382   typedef MachOFormat::ScatteredRelocationEntry<TargetEndianness>
383     ScatteredRelocationEntry;
384   typedef MachOFormat::LoadCommand<TargetEndianness> LoadCommand;
385
386   MachOObjectFileMiddle(MemoryBuffer *Object, bool Is64Bits, error_code &ec);
387
388   const Header *getHeader() const;
389   const LoadCommand *getLoadCommandInfo(unsigned Index) const;
390   const RelocationEntry *getRelocation(DataRefImpl Rel) const;
391   bool isRelocationScattered(const RelocationEntry *RE) const;
392   bool isRelocationPCRel(const RelocationEntry *RE) const;
393   unsigned getRelocationLength(const RelocationEntry *RE) const;
394   unsigned getRelocationTypeImpl(const RelocationEntry *RE) const;
395
396   void moveToNextSymbol(DataRefImpl &DRI) const;
397   void printRelocationTargetName(const RelocationEntry *RE,
398                                  raw_string_ostream &fmt) const;
399   const SectionBase *getSectionBase(DataRefImpl DRI) const;
400   const SymbolTableEntryBase *getSymbolTableEntryBase(DataRefImpl DRI) const;
401   unsigned getCPUType() const;
402
403   // In a MachO file, sections have a segment name. This is used in the .o
404   // files. They have a single segment, but this field specifies which segment
405   // a section should be put in in the final object.
406   StringRef getSectionFinalSegmentName(DataRefImpl Sec) const;
407
408   // Names are stored as 16 bytes. These returns the raw 16 bytes without
409   // interpreting them as a C string.
410   ArrayRef<char> getSectionRawName(DataRefImpl Sec) const;
411   ArrayRef<char> getSectionRawFinalSegmentName(DataRefImpl Sec) const;
412
413   virtual error_code getSymbolFlags(DataRefImpl Symb, uint32_t &Res) const;
414   virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const;
415   virtual error_code getSymbolType(DataRefImpl Symb,
416                                    SymbolRef::Type &Res) const;
417   virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const;
418   virtual error_code getSymbolSection(DataRefImpl Symb,
419                                       section_iterator &Res) const;
420   virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const;
421   virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const;
422   virtual symbol_iterator begin_symbols() const;
423   virtual unsigned getArch() const;
424   virtual StringRef getFileFormatName() const;
425   virtual symbol_iterator end_symbols() const;
426   virtual section_iterator end_sections() const;
427
428   static bool classof(const Binary *v);
429
430 private:
431   // Helper to advance a section or symbol iterator multiple increments at a
432   // time.
433   template<class T>
434   static error_code advance(T &it, size_t Val);
435
436   template<class T>
437   static void advanceTo(T &it, size_t Val);
438 };
439
440 template<class MachOT>
441 struct MachOObjectFileHelperCommon;
442
443 template<endianness TargetEndianness, bool Is64Bits>
444 struct MachOObjectFileHelperCommon<MachOType<TargetEndianness, Is64Bits> > {
445   typedef
446     MachOFormat::SegmentLoadCommand<MachOType<TargetEndianness, Is64Bits> >
447     SegmentLoadCommand;
448   typedef MachOFormat::SymbolTableEntry<MachOType<TargetEndianness, Is64Bits> >
449     SymbolTableEntry;
450   typedef MachOFormat::Section<MachOType<TargetEndianness, Is64Bits> > Section;
451 };
452
453 template<class MachOT>
454 struct MachOObjectFileHelper;
455
456 template<endianness TargetEndianness>
457 struct MachOObjectFileHelper<MachOType<TargetEndianness, false> > :
458     public MachOObjectFileHelperCommon<MachOType<TargetEndianness, false> > {
459   static const macho::LoadCommandType SegmentLoadType = macho::LCT_Segment;
460 };
461
462 template<endianness TargetEndianness>
463 struct MachOObjectFileHelper<MachOType<TargetEndianness, true> > :
464     public MachOObjectFileHelperCommon<MachOType<TargetEndianness, true> > {
465   static const macho::LoadCommandType SegmentLoadType = macho::LCT_Segment64;
466 };
467
468 template<class MachOT>
469 class MachOObjectFile : public MachOObjectFileMiddle<MachOT::TargetEndianness> {
470 public:
471   static const endianness TargetEndianness = MachOT::TargetEndianness;
472   static const bool Is64Bits = MachOT::Is64Bits;
473
474   typedef MachOObjectFileMiddle<MachOT::TargetEndianness> Base;
475   typedef typename Base::RelocationEntry RelocationEntry;
476   typedef typename Base::SectionBase SectionBase;
477   typedef typename Base::SymbolTableEntryBase SymbolTableEntryBase;
478   typedef typename Base::LoadCommand LoadCommand;
479
480   typedef MachOObjectFileHelper<MachOT> Helper;
481   static const macho::LoadCommandType SegmentLoadType = Helper::SegmentLoadType;
482   typedef typename Helper::SegmentLoadCommand SegmentLoadCommand;
483   typedef typename Helper::SymbolTableEntry SymbolTableEntry;
484   typedef typename Helper::Section Section;
485
486   MachOObjectFile(MemoryBuffer *Object, error_code &ec);
487   static bool classof(const Binary *v);
488
489   const Section *getSection(DataRefImpl DRI) const;
490   const SymbolTableEntry *getSymbolTableEntry(DataRefImpl DRI) const;
491   const RelocationEntry *getRelocation(DataRefImpl Rel) const;
492
493   virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const;
494   virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const;
495   virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const;
496   virtual error_code getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const;
497   virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const;
498   virtual error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const;
499   virtual relocation_iterator getSectionRelEnd(DataRefImpl Sec) const;
500   virtual error_code getRelocationAddress(DataRefImpl Rel, uint64_t &Res) const;
501   virtual error_code getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const;
502   virtual error_code getRelocationSymbol(DataRefImpl Rel, SymbolRef &Res) const;
503   virtual error_code getRelocationType(DataRefImpl Rel, uint64_t &Res) const;
504   virtual error_code getRelocationTypeName(DataRefImpl Rel,
505                                            SmallVectorImpl<char> &Result) const;
506   virtual error_code getRelocationValueString(DataRefImpl Rel,
507                                            SmallVectorImpl<char> &Result) const;
508   virtual error_code getRelocationHidden(DataRefImpl Rel, bool &Result) const;
509   virtual error_code getSymbolFileOffset(DataRefImpl Symb, uint64_t &Res) const;
510   virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb,
511                                            bool &Result) const;
512   virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const;
513   virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const;
514   virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const;
515   virtual section_iterator begin_sections() const;
516   void moveToNextSection(DataRefImpl &DRI) const;
517 };
518
519 typedef MachOObjectFileMiddle<support::little> MachOObjectFileLE;
520 typedef MachOObjectFileMiddle<support::big> MachOObjectFileBE;
521
522 typedef MachOObjectFile<MachOType<support::little, false> >
523   MachOObjectFileLE32;
524 typedef MachOObjectFile<MachOType<support::big, false> >
525   MachOObjectFileBE32;
526 typedef MachOObjectFile<MachOType<support::little, true> >
527   MachOObjectFileLE64;
528 typedef MachOObjectFile<MachOType<support::big, true> >
529   MachOObjectFileBE64;
530
531 template<endianness TargetEndianness>
532 MachOObjectFileMiddle<TargetEndianness>::MachOObjectFileMiddle(MemoryBuffer *O,
533                                                                bool Is64Bits,
534                                                                error_code &ec) :
535   MachOObjectFileBase(O, TargetEndianness == support::little, Is64Bits, ec) {
536 }
537
538 template<endianness E>
539 const typename MachOObjectFileMiddle<E>::SymbolTableEntryBase *
540 MachOObjectFileMiddle<E>::getSymbolTableEntryBase(DataRefImpl DRI) const {
541   const LoadCommand *L = getLoadCommandInfo(DRI.d.a);
542   const SymtabLoadCommand *S = reinterpret_cast<const SymtabLoadCommand *>(L);
543
544   unsigned Index = DRI.d.b;
545
546   unsigned SymbolTableEntrySize = is64Bit() ?
547     sizeof(MachOObjectFileLE64::SymbolTableEntry) :
548     sizeof(MachOObjectFileLE32::SymbolTableEntry);
549
550   uint64_t Offset = S->SymbolTableOffset + Index * SymbolTableEntrySize;
551   StringRef Data = getData(Offset, SymbolTableEntrySize);
552   return reinterpret_cast<const SymbolTableEntryBase*>(Data.data());
553 }
554
555 template<endianness E>
556 const typename MachOObjectFileMiddle<E>::Header *
557 MachOObjectFileMiddle<E>::getHeader() const {
558   StringRef Data = getData(0, sizeof(Header));
559   return reinterpret_cast<const Header*>(Data.data());
560 }
561
562 template<endianness E>
563 const typename MachOObjectFileMiddle<E>::LoadCommand *
564 MachOObjectFileMiddle<E>::getLoadCommandInfo(unsigned Index) const {
565   assert(Index < getHeader()->NumLoadCommands);
566   uint64_t Offset;
567   uint64_t NewOffset = getHeaderSize();
568   const LoadCommand *Load;
569   unsigned I = 0;
570   do {
571     Offset = NewOffset;
572     StringRef Data = getData(Offset, sizeof(MachOObjectFileLE::LoadCommand));
573     Load = reinterpret_cast<const LoadCommand*>(Data.data());
574     NewOffset = Offset + Load->Size;
575     ++I;
576   } while (I != Index + 1);
577
578   return reinterpret_cast<const LoadCommand*>(Load);
579 }
580
581 template<endianness E>
582 const typename MachOObjectFileMiddle<E>::RelocationEntry *
583 MachOObjectFileMiddle<E>::getRelocation(DataRefImpl Rel) const {
584   if (const MachOObjectFile<MachOType<E, true> > *O =
585       dyn_cast<MachOObjectFile<MachOType<E, true> > >(this))
586     return O->getRelocation(Rel);
587
588   const MachOObjectFile<MachOType<E, false> > *O =
589     cast<MachOObjectFile<MachOType<E, false> > >(this);
590   return O->getRelocation(Rel);
591 }
592
593 template<endianness E>
594 bool
595 MachOObjectFileMiddle<E>::isRelocationScattered(const RelocationEntry *RE)
596                                                                          const {
597   if (this->getCPUType() == llvm::MachO::CPUTypeX86_64)
598     return false;
599   return RE->Address & macho::RF_Scattered;
600 }
601
602 template<endianness E>
603 bool
604 MachOObjectFileMiddle<E>::isRelocationPCRel(const RelocationEntry *RE) const {
605   typedef MachOObjectFileMiddle<E> ObjType;
606   if (isRelocationScattered(RE)) {
607     const typename MachOObjectFileMiddle<E>::ScatteredRelocationEntry *SRE =
608       reinterpret_cast<const typename ObjType::ScatteredRelocationEntry *>(RE);
609     return SRE->getPCRel();
610   }
611   return RE->getPCRel();
612 }
613
614 template<endianness E>
615 unsigned
616 MachOObjectFileMiddle<E>::getRelocationLength(const RelocationEntry *RE) const {
617   typedef MachOObjectFileMiddle<E> ObjType;
618   if (isRelocationScattered(RE)) {
619     const typename ObjType::ScatteredRelocationEntry *SRE =
620       reinterpret_cast<const typename ObjType::ScatteredRelocationEntry *>(RE);
621     return SRE->getLength();
622   }
623   return RE->getLength();
624 }
625
626 template<endianness E>
627 unsigned
628 MachOObjectFileMiddle<E>::getRelocationTypeImpl(const RelocationEntry *RE)
629                                                                          const {
630   typedef MachOObjectFileMiddle<E> ObjType;
631   if (isRelocationScattered(RE)) {
632     const typename ObjType::ScatteredRelocationEntry *SRE =
633       reinterpret_cast<const typename ObjType::ScatteredRelocationEntry *>(RE);
634     return SRE->getType();
635   }
636   return RE->getType();
637 }
638
639 // Helper to advance a section or symbol iterator multiple increments at a time.
640 template<endianness E>
641 template<class T>
642 error_code MachOObjectFileMiddle<E>::advance(T &it, size_t Val) {
643   error_code ec;
644   while (Val--) {
645     it.increment(ec);
646   }
647   return ec;
648 }
649
650 template<endianness E>
651 template<class T>
652 void MachOObjectFileMiddle<E>::advanceTo(T &it, size_t Val) {
653   if (error_code ec = advance(it, Val))
654     report_fatal_error(ec.message());
655 }
656
657 template<endianness E>
658 void
659 MachOObjectFileMiddle<E>::printRelocationTargetName(const RelocationEntry *RE,
660                                                 raw_string_ostream &fmt) const {
661   bool IsScattered = isRelocationScattered(RE);
662
663   // Target of a scattered relocation is an address.  In the interest of
664   // generating pretty output, scan through the symbol table looking for a
665   // symbol that aligns with that address.  If we find one, print it.
666   // Otherwise, we just print the hex address of the target.
667   if (IsScattered) {
668     uint32_t Val = RE->SymbolNum;
669
670     error_code ec;
671     for (symbol_iterator SI = begin_symbols(), SE = end_symbols(); SI != SE;
672         SI.increment(ec)) {
673       if (ec) report_fatal_error(ec.message());
674
675       uint64_t Addr;
676       StringRef Name;
677
678       if ((ec = SI->getAddress(Addr)))
679         report_fatal_error(ec.message());
680       if (Addr != Val) continue;
681       if ((ec = SI->getName(Name)))
682         report_fatal_error(ec.message());
683       fmt << Name;
684       return;
685     }
686
687     // If we couldn't find a symbol that this relocation refers to, try
688     // to find a section beginning instead.
689     for (section_iterator SI = begin_sections(), SE = end_sections(); SI != SE;
690          SI.increment(ec)) {
691       if (ec) report_fatal_error(ec.message());
692
693       uint64_t Addr;
694       StringRef Name;
695
696       if ((ec = SI->getAddress(Addr)))
697         report_fatal_error(ec.message());
698       if (Addr != Val) continue;
699       if ((ec = SI->getName(Name)))
700         report_fatal_error(ec.message());
701       fmt << Name;
702       return;
703     }
704
705     fmt << format("0x%x", Val);
706     return;
707   }
708
709   StringRef S;
710   bool isExtern = RE->getExternal();
711   uint64_t Val = RE->Address;
712
713   if (isExtern) {
714     symbol_iterator SI = begin_symbols();
715     advanceTo(SI, Val);
716     SI->getName(S);
717   } else {
718     section_iterator SI = begin_sections();
719     advanceTo(SI, Val);
720     SI->getName(S);
721   }
722
723   fmt << S;
724 }
725
726 template<endianness E>
727 const typename MachOObjectFileMiddle<E>::SectionBase *
728 MachOObjectFileMiddle<E>::getSectionBase(DataRefImpl DRI) const {
729   uintptr_t CommandAddr =
730     reinterpret_cast<uintptr_t>(getLoadCommandInfo(DRI.d.a));
731
732   bool Is64 = is64Bit();
733   unsigned SegmentLoadSize =
734     Is64 ? sizeof(MachOObjectFileLE64::SegmentLoadCommand) :
735            sizeof(MachOObjectFileLE32::SegmentLoadCommand);
736   unsigned SectionSize = Is64 ? sizeof(MachOObjectFileLE64::Section) :
737                                 sizeof(MachOObjectFileLE32::Section);
738
739   uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + DRI.d.b * SectionSize;
740   return reinterpret_cast<const SectionBase*>(SectionAddr);
741 }
742
743 template<endianness E>
744 unsigned MachOObjectFileMiddle<E>::getCPUType() const {
745   return getHeader()->CPUType;
746 }
747
748 template<endianness E>
749 void MachOObjectFileMiddle<E>::moveToNextSymbol(DataRefImpl &DRI) const {
750   uint32_t LoadCommandCount = getHeader()->NumLoadCommands;
751   while (DRI.d.a < LoadCommandCount) {
752     const LoadCommand *L = getLoadCommandInfo(DRI.d.a);
753     if (L->Type == macho::LCT_Symtab) {
754       const SymtabLoadCommand *S =
755         reinterpret_cast<const SymtabLoadCommand *>(L);
756       if (DRI.d.b < S->NumSymbolTableEntries)
757         return;
758     }
759
760     DRI.d.a++;
761     DRI.d.b = 0;
762   }
763 }
764
765 template<endianness E>
766 StringRef
767 MachOObjectFileMiddle<E>::getSectionFinalSegmentName(DataRefImpl Sec) const {
768   ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
769   return parseSegmentOrSectionName(Raw.data());
770 }
771
772 template<endianness E>
773 ArrayRef<char>
774 MachOObjectFileMiddle<E>::getSectionRawName(DataRefImpl Sec) const {
775   const SectionBase *Base = getSectionBase(Sec);
776   return ArrayRef<char>(Base->Name);
777 }
778
779 template<endianness E>
780 ArrayRef<char>
781 MachOObjectFileMiddle<E>::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
782   const SectionBase *Base = getSectionBase(Sec);
783   return ArrayRef<char>(Base->SegmentName);
784 }
785
786 template<endianness E>
787 error_code MachOObjectFileMiddle<E>::getSymbolFlags(DataRefImpl DRI,
788                                                     uint32_t &Result) const {
789   const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(DRI);
790
791   uint8_t MachOType = Entry->Type;
792   uint16_t MachOFlags = Entry->Flags;
793
794   // TODO: Correctly set SF_ThreadLocal
795   Result = SymbolRef::SF_None;
796
797   if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
798     Result |= SymbolRef::SF_Undefined;
799
800   if (MachOFlags & macho::STF_StabsEntryMask)
801     Result |= SymbolRef::SF_FormatSpecific;
802
803   if (MachOType & MachO::NlistMaskExternal) {
804     Result |= SymbolRef::SF_Global;
805     if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
806       Result |= SymbolRef::SF_Common;
807   }
808
809   if (MachOFlags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef))
810     Result |= SymbolRef::SF_Weak;
811
812   if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeAbsolute)
813     Result |= SymbolRef::SF_Absolute;
814
815   return object_error::success;
816 }
817
818 template<endianness E>
819 error_code MachOObjectFileMiddle<E>::getSymbolType(DataRefImpl Symb,
820                                                    SymbolRef::Type &Res) const {
821   const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(Symb);
822   uint8_t n_type = Entry->Type;
823
824   Res = SymbolRef::ST_Other;
825
826   // If this is a STAB debugging symbol, we can do nothing more.
827   if (n_type & MachO::NlistMaskStab) {
828     Res = SymbolRef::ST_Debug;
829     return object_error::success;
830   }
831
832   switch (n_type & MachO::NlistMaskType) {
833     case MachO::NListTypeUndefined :
834       Res = SymbolRef::ST_Unknown;
835       break;
836     case MachO::NListTypeSection :
837       Res = SymbolRef::ST_Function;
838       break;
839   }
840   return object_error::success;
841 }
842
843 template<endianness E>
844 error_code MachOObjectFileMiddle<E>::getSymbolName(DataRefImpl Symb,
845                                                    StringRef &Res) const {
846   const LoadCommand *L = getLoadCommandInfo(Symb.d.a);
847   const SymtabLoadCommand *S = reinterpret_cast<const SymtabLoadCommand *>(L);
848   StringRef StringTable = getData(S->StringTableOffset, S->StringTableSize);
849   const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(Symb);
850   const char *Start = &StringTable.data()[Entry->StringIndex];
851   Res = StringRef(Start);
852   return object_error::success;
853 }
854
855 template<endianness E>
856 error_code
857 MachOObjectFileMiddle<E>::getSymbolSection(DataRefImpl Symb,
858                                            section_iterator &Res) const {
859   const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(Symb);
860   uint8_t index = Entry->SectionIndex;
861
862   if (index == 0)
863     Res = end_sections();
864   else
865     Res = section_iterator(SectionRef(Sections[index-1], this));
866
867   return object_error::success;
868 }
869
870
871 template<endianness E>
872 error_code MachOObjectFileMiddle<E>::getSymbolNMTypeChar(DataRefImpl Symb,
873                                                          char &Res) const {
874   const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(Symb);
875   uint8_t Type = Entry->Type;
876   uint16_t Flags = Entry->Flags;
877
878   char Char;
879   switch (Type & macho::STF_TypeMask) {
880     case macho::STT_Undefined:
881       Char = 'u';
882       break;
883     case macho::STT_Absolute:
884     case macho::STT_Section:
885       Char = 's';
886       break;
887     default:
888       Char = '?';
889       break;
890   }
891
892   if (Flags & (macho::STF_External | macho::STF_PrivateExtern))
893     Char = toupper(static_cast<unsigned char>(Char));
894   Res = Char;
895   return object_error::success;
896 }
897
898 template<endianness E>
899 error_code
900 MachOObjectFileMiddle<E>::getSectionName(DataRefImpl Sec,
901                                          StringRef &Result) const {
902   ArrayRef<char> Raw = getSectionRawName(Sec);
903   Result = parseSegmentOrSectionName(Raw.data());
904   return object_error::success;
905 }
906
907 template<endianness E>
908 error_code MachOObjectFileMiddle<E>::getSymbolNext(DataRefImpl Symb,
909                                                      SymbolRef &Res) const {
910   Symb.d.b++;
911   moveToNextSymbol(Symb);
912   Res = SymbolRef(Symb, this);
913   return object_error::success;
914 }
915
916 template<endianness E>
917 symbol_iterator MachOObjectFileMiddle<E>::begin_symbols() const {
918   // DRI.d.a = segment number; DRI.d.b = symbol index.
919   DataRefImpl DRI;
920   moveToNextSymbol(DRI);
921   return symbol_iterator(SymbolRef(DRI, this));
922 }
923
924 template<endianness E>
925 unsigned MachOObjectFileMiddle<E>::getArch() const {
926   switch (getCPUType()) {
927   case llvm::MachO::CPUTypeI386:
928     return Triple::x86;
929   case llvm::MachO::CPUTypeX86_64:
930     return Triple::x86_64;
931   case llvm::MachO::CPUTypeARM:
932     return Triple::arm;
933   case llvm::MachO::CPUTypePowerPC:
934     return Triple::ppc;
935   case llvm::MachO::CPUTypePowerPC64:
936     return Triple::ppc64;
937   default:
938     return Triple::UnknownArch;
939   }
940 }
941
942 template<endianness E>
943 StringRef MachOObjectFileMiddle<E>::getFileFormatName() const {
944   unsigned CPUType = getCPUType();
945   if (!is64Bit()) {
946     switch (CPUType) {
947     case llvm::MachO::CPUTypeI386:
948       return "Mach-O 32-bit i386";
949     case llvm::MachO::CPUTypeARM:
950       return "Mach-O arm";
951     case llvm::MachO::CPUTypePowerPC:
952       return "Mach-O 32-bit ppc";
953     default:
954       assert((CPUType & llvm::MachO::CPUArchABI64) == 0 &&
955              "64-bit object file when we're not 64-bit?");
956       return "Mach-O 32-bit unknown";
957     }
958   }
959
960   // Make sure the cpu type has the correct mask.
961   assert((CPUType & llvm::MachO::CPUArchABI64)
962          == llvm::MachO::CPUArchABI64 &&
963          "32-bit object file when we're 64-bit?");
964
965   switch (CPUType) {
966   case llvm::MachO::CPUTypeX86_64:
967     return "Mach-O 64-bit x86-64";
968   case llvm::MachO::CPUTypePowerPC64:
969     return "Mach-O 64-bit ppc64";
970   default:
971     return "Mach-O 64-bit unknown";
972   }
973 }
974
975 template<endianness E>
976 symbol_iterator MachOObjectFileMiddle<E>::end_symbols() const {
977   DataRefImpl DRI;
978   DRI.d.a = getHeader()->NumLoadCommands;
979   return symbol_iterator(SymbolRef(DRI, this));
980 }
981
982 template<endianness E>
983 section_iterator MachOObjectFileMiddle<E>::end_sections() const {
984   DataRefImpl DRI;
985   DRI.d.a = getHeader()->NumLoadCommands;
986   return section_iterator(SectionRef(DRI, this));
987 }
988
989 template<endianness E>
990 bool MachOObjectFileMiddle<E>::classof(const Binary *v) {
991   return isa<MachOObjectFile<MachOType<E, false> > >(v) ||
992     isa<MachOObjectFile<MachOType<E, true> > >(v);
993 }
994
995 template<class MachOT>
996 MachOObjectFile<MachOT>::MachOObjectFile(MemoryBuffer *Object,
997                                          error_code &ec) :
998   MachOObjectFileMiddle<TargetEndianness>(Object, Is64Bits, ec) {
999   DataRefImpl DRI;
1000   moveToNextSection(DRI);
1001   uint32_t LoadCommandCount = this->getHeader()->NumLoadCommands;
1002   while (DRI.d.a < LoadCommandCount) {
1003     this->Sections.push_back(DRI);
1004     DRI.d.b++;
1005     moveToNextSection(DRI);
1006   }
1007 }
1008
1009 template<class MachOT>
1010 bool MachOObjectFile<MachOT>::classof(const Binary *v) {
1011   return v->getType() ==
1012     Base::getMachOType(TargetEndianness == support::little, Is64Bits);
1013 }
1014
1015 template<class MachOT>
1016 const typename MachOObjectFile<MachOT>::Section *
1017 MachOObjectFile<MachOT>::getSection(DataRefImpl DRI) const {
1018   const SectionBase *Addr = this->getSectionBase(DRI);
1019   return reinterpret_cast<const Section*>(Addr);
1020 }
1021
1022 template<class MachOT>
1023 const typename MachOObjectFile<MachOT>::SymbolTableEntry *
1024 MachOObjectFile<MachOT>::getSymbolTableEntry(DataRefImpl DRI) const {
1025   const SymbolTableEntryBase *Base = this->getSymbolTableEntryBase(DRI);
1026   return reinterpret_cast<const SymbolTableEntry*>(Base);
1027 }
1028
1029 template<class MachOT>
1030 const typename MachOObjectFile<MachOT>::RelocationEntry *
1031 MachOObjectFile<MachOT>::getRelocation(DataRefImpl Rel) const {
1032   const Section *Sect = getSection(this->Sections[Rel.d.b]);
1033   uint32_t RelOffset = Sect->RelocationTableOffset;
1034   uint64_t Offset = RelOffset + Rel.d.a * sizeof(RelocationEntry);
1035   StringRef Data = this->getData(Offset, sizeof(RelocationEntry));
1036   return reinterpret_cast<const RelocationEntry*>(Data.data());
1037 }
1038
1039 template<class MachOT>
1040 error_code
1041 MachOObjectFile<MachOT>::getSectionAddress(DataRefImpl Sec,
1042                                            uint64_t &Res) const {
1043   const Section *Sect = getSection(Sec);
1044   Res = Sect->Address;
1045   return object_error::success;
1046 }
1047
1048 template<class MachOT>
1049 error_code
1050 MachOObjectFile<MachOT>::getSectionSize(DataRefImpl Sec,
1051                                         uint64_t &Res) const {
1052   const Section *Sect = getSection(Sec);
1053   Res = Sect->Size;
1054   return object_error::success;
1055 }
1056
1057 template<class MachOT>
1058 error_code
1059 MachOObjectFile<MachOT>::getSectionContents(DataRefImpl Sec,
1060                                             StringRef &Res) const {
1061   const Section *Sect = getSection(Sec);
1062   Res = this->getData(Sect->Offset, Sect->Size);
1063   return object_error::success;
1064 }
1065
1066 template<class MachOT>
1067 error_code
1068 MachOObjectFile<MachOT>::getSectionAlignment(DataRefImpl Sec,
1069                                              uint64_t &Res) const {
1070   const Section *Sect = getSection(Sec);
1071   Res = uint64_t(1) << Sect->Align;
1072   return object_error::success;
1073 }
1074
1075 template<class MachOT>
1076 error_code
1077 MachOObjectFile<MachOT>::isSectionText(DataRefImpl Sec, bool &Res) const {
1078   const Section *Sect = getSection(Sec);
1079   Res = Sect->Flags & macho::SF_PureInstructions;
1080   return object_error::success;
1081 }
1082
1083 template<class MachOT>
1084 error_code
1085 MachOObjectFile<MachOT>::isSectionZeroInit(DataRefImpl Sec, bool &Res) const {
1086   const Section *Sect = getSection(Sec);
1087   unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType;
1088   Res = SectionType == MachO::SectionTypeZeroFill ||
1089     SectionType == MachO::SectionTypeZeroFillLarge;
1090   return object_error::success;
1091 }
1092
1093 template<class MachOT>
1094 relocation_iterator
1095 MachOObjectFile<MachOT>::getSectionRelEnd(DataRefImpl Sec) const {
1096   const Section *Sect = getSection(Sec);
1097   uint32_t LastReloc = Sect->NumRelocationTableEntries;
1098   DataRefImpl Ret;
1099   Ret.d.a = LastReloc;
1100   Ret.d.b = this->getSectionIndex(Sec);
1101   return relocation_iterator(RelocationRef(Ret, this));
1102 }
1103
1104 template<class MachOT>
1105 error_code
1106 MachOObjectFile<MachOT>::getRelocationAddress(DataRefImpl Rel,
1107                                               uint64_t &Res) const {
1108   const Section *Sect = getSection(this->Sections[Rel.d.b]);
1109   uint64_t SectAddress = Sect->Address;
1110   const RelocationEntry *RE = getRelocation(Rel);
1111
1112   uint64_t RelAddr;
1113   if (this->isRelocationScattered(RE))
1114     RelAddr = RE->Address & 0xFFFFFF;
1115   else
1116     RelAddr = RE->Address;
1117
1118   Res = SectAddress + RelAddr;
1119   return object_error::success;
1120 }
1121
1122 template<class MachOT>
1123 error_code
1124 MachOObjectFile<MachOT>::getRelocationOffset(DataRefImpl Rel,
1125                                              uint64_t &Res) const {
1126   const RelocationEntry *RE = getRelocation(Rel);
1127   if (this->isRelocationScattered(RE))
1128     Res = RE->Address & 0xFFFFFF;
1129   else
1130     Res = RE->Address;
1131   return object_error::success;
1132 }
1133
1134 template<class MachOT>
1135 error_code
1136 MachOObjectFile<MachOT>::getRelocationSymbol(DataRefImpl Rel,
1137                                              SymbolRef &Res) const {
1138   const RelocationEntry *RE = getRelocation(Rel);
1139   uint32_t SymbolIdx = RE->SymbolNum;
1140   bool isExtern = RE->getExternal();
1141
1142   DataRefImpl Sym;
1143   this->moveToNextSymbol(Sym);
1144   if (isExtern) {
1145     for (unsigned i = 0; i < SymbolIdx; i++) {
1146       Sym.d.b++;
1147       this->moveToNextSymbol(Sym);
1148       assert(Sym.d.a < this->getHeader()->NumLoadCommands &&
1149              "Relocation symbol index out of range!");
1150     }
1151   }
1152   Res = SymbolRef(Sym, this);
1153   return object_error::success;
1154 }
1155
1156 template<class MachOT>
1157 error_code MachOObjectFile<MachOT>::getRelocationType(DataRefImpl Rel,
1158                                                       uint64_t &Res) const {
1159   const RelocationEntry *RE = getRelocation(Rel);
1160   Res = this->getRelocationTypeImpl(RE);
1161   return object_error::success;
1162 }
1163
1164 template<class MachOT>
1165 error_code
1166 MachOObjectFile<MachOT>::getRelocationTypeName(DataRefImpl Rel,
1167                                           SmallVectorImpl<char> &Result) const {
1168     // TODO: Support scattered relocations.
1169   StringRef res;
1170   const RelocationEntry *RE = getRelocation(Rel);
1171
1172   unsigned Arch = this->getArch();
1173
1174   unsigned r_type = this->getRelocationTypeImpl(RE);
1175
1176   switch (Arch) {
1177     case Triple::x86: {
1178       static const char *const Table[] =  {
1179         "GENERIC_RELOC_VANILLA",
1180         "GENERIC_RELOC_PAIR",
1181         "GENERIC_RELOC_SECTDIFF",
1182         "GENERIC_RELOC_PB_LA_PTR",
1183         "GENERIC_RELOC_LOCAL_SECTDIFF",
1184         "GENERIC_RELOC_TLV" };
1185
1186       if (r_type > 6)
1187         res = "Unknown";
1188       else
1189         res = Table[r_type];
1190       break;
1191     }
1192     case Triple::x86_64: {
1193       static const char *const Table[] =  {
1194         "X86_64_RELOC_UNSIGNED",
1195         "X86_64_RELOC_SIGNED",
1196         "X86_64_RELOC_BRANCH",
1197         "X86_64_RELOC_GOT_LOAD",
1198         "X86_64_RELOC_GOT",
1199         "X86_64_RELOC_SUBTRACTOR",
1200         "X86_64_RELOC_SIGNED_1",
1201         "X86_64_RELOC_SIGNED_2",
1202         "X86_64_RELOC_SIGNED_4",
1203         "X86_64_RELOC_TLV" };
1204
1205       if (r_type > 9)
1206         res = "Unknown";
1207       else
1208         res = Table[r_type];
1209       break;
1210     }
1211     case Triple::arm: {
1212       static const char *const Table[] =  {
1213         "ARM_RELOC_VANILLA",
1214         "ARM_RELOC_PAIR",
1215         "ARM_RELOC_SECTDIFF",
1216         "ARM_RELOC_LOCAL_SECTDIFF",
1217         "ARM_RELOC_PB_LA_PTR",
1218         "ARM_RELOC_BR24",
1219         "ARM_THUMB_RELOC_BR22",
1220         "ARM_THUMB_32BIT_BRANCH",
1221         "ARM_RELOC_HALF",
1222         "ARM_RELOC_HALF_SECTDIFF" };
1223
1224       if (r_type > 9)
1225         res = "Unknown";
1226       else
1227         res = Table[r_type];
1228       break;
1229     }
1230     case Triple::ppc: {
1231       static const char *const Table[] =  {
1232         "PPC_RELOC_VANILLA",
1233         "PPC_RELOC_PAIR",
1234         "PPC_RELOC_BR14",
1235         "PPC_RELOC_BR24",
1236         "PPC_RELOC_HI16",
1237         "PPC_RELOC_LO16",
1238         "PPC_RELOC_HA16",
1239         "PPC_RELOC_LO14",
1240         "PPC_RELOC_SECTDIFF",
1241         "PPC_RELOC_PB_LA_PTR",
1242         "PPC_RELOC_HI16_SECTDIFF",
1243         "PPC_RELOC_LO16_SECTDIFF",
1244         "PPC_RELOC_HA16_SECTDIFF",
1245         "PPC_RELOC_JBSR",
1246         "PPC_RELOC_LO14_SECTDIFF",
1247         "PPC_RELOC_LOCAL_SECTDIFF" };
1248
1249       res = Table[r_type];
1250       break;
1251     }
1252     case Triple::UnknownArch:
1253       res = "Unknown";
1254       break;
1255   }
1256   Result.append(res.begin(), res.end());
1257   return object_error::success;
1258 }
1259
1260 template<class MachOT>
1261 error_code
1262 MachOObjectFile<MachOT>::getRelocationValueString(DataRefImpl Rel,
1263                                           SmallVectorImpl<char> &Result) const {
1264   const RelocationEntry *RE = getRelocation(Rel);
1265
1266   unsigned Arch = this->getArch();
1267   bool IsScattered = this->isRelocationScattered(RE);
1268
1269   std::string fmtbuf;
1270   raw_string_ostream fmt(fmtbuf);
1271
1272   unsigned Type = this->getRelocationTypeImpl(RE);
1273   bool IsPCRel = this->isRelocationPCRel(RE);
1274
1275   // Determine any addends that should be displayed with the relocation.
1276   // These require decoding the relocation type, which is triple-specific.
1277
1278   // X86_64 has entirely custom relocation types.
1279   if (Arch == Triple::x86_64) {
1280     bool isPCRel = RE->getPCRel();
1281
1282     switch (Type) {
1283       case macho::RIT_X86_64_GOTLoad:   // X86_64_RELOC_GOT_LOAD
1284       case macho::RIT_X86_64_GOT: {     // X86_64_RELOC_GOT
1285         this->printRelocationTargetName(RE, fmt);
1286         fmt << "@GOT";
1287         if (isPCRel) fmt << "PCREL";
1288         break;
1289       }
1290       case macho::RIT_X86_64_Subtractor: { // X86_64_RELOC_SUBTRACTOR
1291         DataRefImpl RelNext = Rel;
1292         RelNext.d.a++;
1293         const RelocationEntry *RENext = getRelocation(RelNext);
1294
1295         // X86_64_SUBTRACTOR must be followed by a relocation of type
1296         // X86_64_RELOC_UNSIGNED.
1297         // NOTE: Scattered relocations don't exist on x86_64.
1298         unsigned RType = RENext->getType();
1299         if (RType != 0)
1300           report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
1301                              "X86_64_RELOC_SUBTRACTOR.");
1302
1303         // The X86_64_RELOC_UNSIGNED contains the minuend symbol,
1304         // X86_64_SUBTRACTOR contains to the subtrahend.
1305         this->printRelocationTargetName(RENext, fmt);
1306         fmt << "-";
1307         this->printRelocationTargetName(RE, fmt);
1308         break;
1309       }
1310       case macho::RIT_X86_64_TLV:
1311         this->printRelocationTargetName(RE, fmt);
1312         fmt << "@TLV";
1313         if (isPCRel) fmt << "P";
1314         break;
1315       case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1
1316         this->printRelocationTargetName(RE, fmt);
1317         fmt << "-1";
1318         break;
1319       case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2
1320         this->printRelocationTargetName(RE, fmt);
1321         fmt << "-2";
1322         break;
1323       case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4
1324         this->printRelocationTargetName(RE, fmt);
1325         fmt << "-4";
1326         break;
1327       default:
1328         this->printRelocationTargetName(RE, fmt);
1329         break;
1330     }
1331   // X86 and ARM share some relocation types in common.
1332   } else if (Arch == Triple::x86 || Arch == Triple::arm) {
1333     // Generic relocation types...
1334     switch (Type) {
1335       case macho::RIT_Pair: // GENERIC_RELOC_PAIR - prints no info
1336         return object_error::success;
1337       case macho::RIT_Difference: { // GENERIC_RELOC_SECTDIFF
1338         DataRefImpl RelNext = Rel;
1339         RelNext.d.a++;
1340         const RelocationEntry *RENext = getRelocation(RelNext);
1341
1342         // X86 sect diff's must be followed by a relocation of type
1343         // GENERIC_RELOC_PAIR.
1344         bool isNextScattered = (Arch != Triple::x86_64) &&
1345                                (RENext->Address & macho::RF_Scattered);
1346         unsigned RType;
1347         if (isNextScattered)
1348           RType = (RENext->Address >> 24) & 0xF;
1349         else
1350           RType = RENext->getType();
1351         if (RType != 1)
1352           report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1353                              "GENERIC_RELOC_SECTDIFF.");
1354
1355         this->printRelocationTargetName(RE, fmt);
1356         fmt << "-";
1357         this->printRelocationTargetName(RENext, fmt);
1358         break;
1359       }
1360     }
1361
1362     if (Arch == Triple::x86) {
1363       // All X86 relocations that need special printing were already
1364       // handled in the generic code.
1365       switch (Type) {
1366         case macho::RIT_Generic_LocalDifference:{// GENERIC_RELOC_LOCAL_SECTDIFF
1367           DataRefImpl RelNext = Rel;
1368           RelNext.d.a++;
1369           const RelocationEntry *RENext = getRelocation(RelNext);
1370
1371           // X86 sect diff's must be followed by a relocation of type
1372           // GENERIC_RELOC_PAIR.
1373           bool isNextScattered = (Arch != Triple::x86_64) &&
1374                                (RENext->Address & macho::RF_Scattered);
1375           unsigned RType;
1376           if (isNextScattered)
1377             RType = (RENext->Address >> 24) & 0xF;
1378           else
1379             RType = RENext->getType();
1380           if (RType != 1)
1381             report_fatal_error("Expected GENERIC_RELOC_PAIR after "
1382                                "GENERIC_RELOC_LOCAL_SECTDIFF.");
1383
1384           this->printRelocationTargetName(RE, fmt);
1385           fmt << "-";
1386           this->printRelocationTargetName(RENext, fmt);
1387           break;
1388         }
1389         case macho::RIT_Generic_TLV: {
1390           this->printRelocationTargetName(RE, fmt);
1391           fmt << "@TLV";
1392           if (IsPCRel) fmt << "P";
1393           break;
1394         }
1395         default:
1396           this->printRelocationTargetName(RE, fmt);
1397       }
1398     } else { // ARM-specific relocations
1399       switch (Type) {
1400         case macho::RIT_ARM_Half:             // ARM_RELOC_HALF
1401         case macho::RIT_ARM_HalfDifference: { // ARM_RELOC_HALF_SECTDIFF
1402           // Half relocations steal a bit from the length field to encode
1403           // whether this is an upper16 or a lower16 relocation.
1404           bool isUpper;
1405           if (IsScattered)
1406             isUpper = (RE->Address >> 28) & 1;
1407           else
1408             isUpper = (RE->getLength() >> 1) & 1;
1409
1410           if (isUpper)
1411             fmt << ":upper16:(";
1412           else
1413             fmt << ":lower16:(";
1414           this->printRelocationTargetName(RE, fmt);
1415
1416           DataRefImpl RelNext = Rel;
1417           RelNext.d.a++;
1418           const RelocationEntry *RENext = getRelocation(RelNext);
1419
1420           // ARM half relocs must be followed by a relocation of type
1421           // ARM_RELOC_PAIR.
1422           bool isNextScattered = (Arch != Triple::x86_64) &&
1423                                  (RENext->Address & macho::RF_Scattered);
1424           unsigned RType;
1425           if (isNextScattered)
1426             RType = (RENext->Address >> 24) & 0xF;
1427           else
1428             RType = RENext->getType();
1429
1430           if (RType != 1)
1431             report_fatal_error("Expected ARM_RELOC_PAIR after "
1432                                "GENERIC_RELOC_HALF");
1433
1434           // NOTE: The half of the target virtual address is stashed in the
1435           // address field of the secondary relocation, but we can't reverse
1436           // engineer the constant offset from it without decoding the movw/movt
1437           // instruction to find the other half in its immediate field.
1438
1439           // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
1440           // symbol/section pointer of the follow-on relocation.
1441           if (Type == macho::RIT_ARM_HalfDifference) {
1442             fmt << "-";
1443             this->printRelocationTargetName(RENext, fmt);
1444           }
1445
1446           fmt << ")";
1447           break;
1448         }
1449         default: {
1450           this->printRelocationTargetName(RE, fmt);
1451         }
1452       }
1453     }
1454   } else
1455     this->printRelocationTargetName(RE, fmt);
1456
1457   fmt.flush();
1458   Result.append(fmtbuf.begin(), fmtbuf.end());
1459   return object_error::success;
1460 }
1461
1462 template<class MachOT>
1463 error_code
1464 MachOObjectFile<MachOT>::getRelocationHidden(DataRefImpl Rel,
1465                                              bool &Result) const {
1466   const RelocationEntry *RE = getRelocation(Rel);
1467   unsigned Arch = this->getArch();
1468   unsigned Type = this->getRelocationTypeImpl(RE);
1469
1470   Result = false;
1471
1472   // On arches that use the generic relocations, GENERIC_RELOC_PAIR
1473   // is always hidden.
1474   if (Arch == Triple::x86 || Arch == Triple::arm) {
1475     if (Type == macho::RIT_Pair) Result = true;
1476   } else if (Arch == Triple::x86_64) {
1477     // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
1478     // an X864_64_RELOC_SUBTRACTOR.
1479     if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) {
1480       DataRefImpl RelPrev = Rel;
1481       RelPrev.d.a--;
1482       const RelocationEntry *REPrev = this->getRelocation(RelPrev);
1483
1484       unsigned PrevType = REPrev->getType();
1485
1486       if (PrevType == macho::RIT_X86_64_Subtractor) Result = true;
1487     }
1488   }
1489
1490   return object_error::success;
1491 }
1492
1493 template<class MachOT>
1494 error_code
1495 MachOObjectFile<MachOT>::getSymbolFileOffset(DataRefImpl Symb,
1496                                              uint64_t &Res) const {
1497   const SymbolTableEntry *Entry = getSymbolTableEntry(Symb);
1498   Res = Entry->Value;
1499   if (Entry->SectionIndex) {
1500     const Section *Sec =
1501       this->getSection(this->Sections[Entry->SectionIndex-1]);
1502     Res += Sec->Offset - Sec->Address;
1503   }
1504
1505   return object_error::success;
1506 }
1507
1508 template<class MachOT>
1509 error_code
1510 MachOObjectFile<MachOT>::sectionContainsSymbol(DataRefImpl Sec,
1511                                                DataRefImpl Symb,
1512                                                bool &Result) const {
1513   SymbolRef::Type ST;
1514   this->getSymbolType(Symb, ST);
1515   if (ST == SymbolRef::ST_Unknown) {
1516     Result = false;
1517     return object_error::success;
1518   }
1519
1520   uint64_t SectBegin, SectEnd;
1521   getSectionAddress(Sec, SectBegin);
1522   getSectionSize(Sec, SectEnd);
1523   SectEnd += SectBegin;
1524
1525   const SymbolTableEntry *Entry = getSymbolTableEntry(Symb);
1526   uint64_t SymAddr= Entry->Value;
1527   Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
1528
1529   return object_error::success;
1530 }
1531
1532 template<class MachOT>
1533 error_code MachOObjectFile<MachOT>::getSymbolAddress(DataRefImpl Symb,
1534                                                      uint64_t &Res) const {
1535   const SymbolTableEntry *Entry = getSymbolTableEntry(Symb);
1536   Res = Entry->Value;
1537   return object_error::success;
1538 }
1539
1540 template<class MachOT>
1541 error_code MachOObjectFile<MachOT>::getSymbolSize(DataRefImpl DRI,
1542                                                     uint64_t &Result) const {
1543   uint32_t LoadCommandCount = this->getHeader()->NumLoadCommands;
1544   uint64_t BeginOffset;
1545   uint64_t EndOffset = 0;
1546   uint8_t SectionIndex;
1547
1548   const SymbolTableEntry *Entry = getSymbolTableEntry(DRI);
1549   BeginOffset = Entry->Value;
1550   SectionIndex = Entry->SectionIndex;
1551   if (!SectionIndex) {
1552     uint32_t flags = SymbolRef::SF_None;
1553     this->getSymbolFlags(DRI, flags);
1554     if (flags & SymbolRef::SF_Common)
1555       Result = Entry->Value;
1556     else
1557       Result = UnknownAddressOrSize;
1558     return object_error::success;
1559   }
1560   // Unfortunately symbols are unsorted so we need to touch all
1561   // symbols from load command
1562   DRI.d.b = 0;
1563   uint32_t Command = DRI.d.a;
1564   while (Command == DRI.d.a) {
1565     this->moveToNextSymbol(DRI);
1566     if (DRI.d.a < LoadCommandCount) {
1567       Entry = getSymbolTableEntry(DRI);
1568       if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset)
1569         if (!EndOffset || Entry->Value < EndOffset)
1570           EndOffset = Entry->Value;
1571     }
1572     DRI.d.b++;
1573   }
1574   if (!EndOffset) {
1575     uint64_t Size;
1576     this->getSectionSize(this->Sections[SectionIndex-1], Size);
1577     this->getSectionAddress(this->Sections[SectionIndex-1], EndOffset);
1578     EndOffset += Size;
1579   }
1580   Result = EndOffset - BeginOffset;
1581   return object_error::success;
1582 }
1583
1584 template<class MachOT>
1585 error_code MachOObjectFile<MachOT>::getSectionNext(DataRefImpl Sec,
1586                                                    SectionRef &Res) const {
1587   Sec.d.b++;
1588   moveToNextSection(Sec);
1589   Res = SectionRef(Sec, this);
1590   return object_error::success;
1591 }
1592
1593 template<class MachOT>
1594 section_iterator MachOObjectFile<MachOT>::begin_sections() const {
1595   DataRefImpl DRI;
1596   moveToNextSection(DRI);
1597   return section_iterator(SectionRef(DRI, this));
1598 }
1599
1600 template<class MachOT>
1601 void MachOObjectFile<MachOT>::moveToNextSection(DataRefImpl &DRI) const {
1602   uint32_t LoadCommandCount = this->getHeader()->NumLoadCommands;
1603   while (DRI.d.a < LoadCommandCount) {
1604     const LoadCommand *Command = this->getLoadCommandInfo(DRI.d.a);
1605     if (Command->Type == SegmentLoadType) {
1606       const SegmentLoadCommand *SegmentLoadCmd =
1607         reinterpret_cast<const SegmentLoadCommand*>(Command);
1608       if (DRI.d.b < SegmentLoadCmd->NumSections)
1609         return;
1610     }
1611
1612     DRI.d.a++;
1613     DRI.d.b = 0;
1614   }
1615 }
1616
1617 }
1618 }
1619
1620 #endif
1621