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