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