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